package com.lolc.engine;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import com.lolc.LoLAutoCounterManager;
import com.lolc.bean.Champion;
import com.lolc.bean.Lane;
import com.lolc.bean.Pick;
import com.lolc.ihm.PlayerSelection;
import com.lolc.utils.Constant;

public class CounterAffinityEngine {

	private List<PlayerSelection> opponentsCharacters;
	private List<PlayerSelection> teamCharacters;
	private List<Lane> teamLanes;

	// private Properties prop = new Properties();

	public CounterAffinityEngine() {
		/*
		 * try { // prop.load(new
		 * FileInputStream("./config/configuration.properties")); //TODO fill
		 * this constructor } catch (FileNotFoundException e) { // TODO
		 * Auto-generated catch block e.printStackTrace(); } catch (IOException
		 * e) { // TODO Auto-generated catch block e.printStackTrace(); }
		 */
		this.teamCharacters = new ArrayList<PlayerSelection>();
		this.opponentsCharacters = new ArrayList<PlayerSelection>();
		this.teamLanes = new ArrayList<Lane>();
		for (int i = 0; i < Constant.NUMBER_PLAYER_PER_TEAM; i++) {
			if (LoLAutoCounterManager.getInstance().getMyTeamSelections()[i] != null
					&& LoLAutoCounterManager.getInstance().getMyTeamSelections()[i].getChampion() != null) {
				this.teamCharacters.add(LoLAutoCounterManager.getInstance().getMyTeamSelections()[i]);
			}

			if (LoLAutoCounterManager.getInstance().getMyTeamSelections()[i] != null
					&& LoLAutoCounterManager.getInstance().getMyTeamSelections()[i].getLane() != null
					&& LoLAutoCounterManager.getInstance().getMyTeamSelections()[i].getChampion() != null) {
				this.teamLanes.add(LoLAutoCounterManager.getInstance().getMyTeamSelections()[i].getLane());
			}

			if (LoLAutoCounterManager.getInstance().getEnnemySelections()[i] != null
					&& LoLAutoCounterManager.getInstance().getEnnemySelections()[i].getChampion() != null) {
				this.opponentsCharacters.add(LoLAutoCounterManager.getInstance().getEnnemySelections()[i]);
			}
		}
	}

	/**
	 * 
	 * @param withLanes
	 *            If the lane positions are asked
	 * @param bans
	 *            the Champions banned
	 * @return
	 */
	public List<Champion> calculateCountersAffinities() {

		LoLAutoCounterManager.getLogger().info("");
		LoLAutoCounterManager.getLogger().info("RATIO IN PROGRESS...");
		// JHE
		// creates the counter list for the weight of characters
		List<Champion> champions = new ArrayList<Champion>();
		List<Float> ratios = new ArrayList<Float>();

		List<Champion> bans = Arrays.asList(LoLAutoCounterManager.getInstance().getBannedChampions());

		for (Champion champion : LoLAutoCounterManager.getInstance().getChampionsList()) {

			// skip champion already chosen
			PlayerSelection ps = new PlayerSelection(champion, null);
			if (bans.contains(champion) || teamCharacters.contains(ps) || opponentsCharacters.contains(ps)) {
				continue;
			}

			// take champion on chosen lane
			if (LoLAutoCounterManager.getInstance().getLane() != null
					&& !champion.getLanes().contains(LoLAutoCounterManager.getInstance().getLane())) {
				continue;
			}

			// My Synergies
			float synergieRatio = 0;
			for (PlayerSelection championTeam : teamCharacters) {
				if (championTeam != null && championTeam.getChampion() != null) {
					for (Pick synergie : champion.getSynergies()) {
						if (synergie.getChampion().equals(championTeam.getChampion())) {
							synergieRatio += synergie.getRatio();
						}
					}
				}
			}

			// I Counter
			float counterGood = 0;
			// I am countered
			float counterBad = 0;

			// If I chose a lane
			if (LoLAutoCounterManager.getInstance().getLane() != null) {
				boolean sameLaneFound = false;
				for (PlayerSelection championVs : opponentsCharacters) {
					if (championVs != null && championVs.getChampion() != null) {

						// Get champion enemy on same lane if exists
						if (championVs.getLane().equals(LoLAutoCounterManager.getInstance().getLane())) {

							// SAME LANE FOUND !!
							sameLaneFound = true;
							// calculate counter ratio according to LANE counter
							// stats if exists

							Lane laneVs = championVs.getChampion().getLane(
									LoLAutoCounterManager.getInstance().getLane());
							if (laneVs != null) {
								// current champion vs has counter stats on the
								// chosen lane
								counterGood += getScoreCounter(champion, championVs.getChampion(), laneVs);

							} else {
								// current champion vs has NO counter stats on
								// the chosen lane
								counterGood += getScoreCounter(champion, championVs.getChampion());

							}
							Lane laneMy = champion.getLane(LoLAutoCounterManager.getInstance().getLane());
							if (laneMy != null) {
								// current champion my has counter stats on the
								// chosen lane
								counterBad += getScoreCounter(championVs.getChampion(), champion, laneMy);

							} else {
								// current champion my has NO counter stats on
								// the chosen lane
								counterBad += getScoreCounter(championVs.getChampion(), champion);
							}
						}
					}
				}

				// SAME LANE NOT FOUND !!
				if (!sameLaneFound) {

					// calculate counter ratio according to general ratio with
					// champion vs on a lane not mentioned in my team
					for (PlayerSelection championVs : opponentsCharacters) {
						if (championVs != null && championVs.getChampion() != null) {

							counterGood += getScoreCounter(champion, championVs.getChampion());

							counterBad += getScoreCounter(championVs.getChampion(), champion);

						}
					}
				}
			} else {

				// NO LANE SELECTED
				// calculate counter ratio according to enemy team without lane
				// with general ratio
				// and enemy team with lane with lane ratio

				for (PlayerSelection championVs : opponentsCharacters) {
					if (championVs != null) {

						if (championVs.getLane() != null && teamLanes.contains(championVs.getLane())) {
							// skip this enemy champion because a lane is
							// selected and on team size a champion has the same
							// lane
						} else if (championVs.getLane() != null) {
							// calculate counter ratio with lane ratio if a lane
							// is selected on enemy
							Lane laneVs = championVs.getChampion().getLane(
									LoLAutoCounterManager.getInstance().getLane());
							if (laneVs != null) {
								counterGood += getScoreCounter(champion, championVs.getChampion(), laneVs);

							} else {
								counterGood += getScoreCounter(champion, championVs.getChampion());

							}

							Lane laneMy = champion.getLane(championVs.getLane());
							if (laneMy != null) {
								// current champion my has counter stats on the
								// lane of the enemy champion
								counterBad += getScoreCounter(championVs.getChampion(), championVs.getChampion(), laneMy);

							} else {
								// calculate counter ratio on general data of te
								// champion
								counterBad += getScoreCounter(championVs.getChampion(), champion);
							}
						} else {
							// calculate counter ratio with general ratio if no
							// lane selected on enemy
							counterBad += getScoreCounter(championVs.getChampion(), champion);
						}
						//

					}
				}
			}

			float finalRatio = synergieRatio + counterGood - counterBad;
			champions.add(champion);
			ratios.add(finalRatio);
		}

		List<Champion> betterChampions = new ArrayList<Champion>();
		List<Float> betterRatios = new ArrayList<Float>();

		while (champions.size() > 0) {
			Float maxRatio = null;
			Champion betterChampion = null;
			int imax = -1;
			for (int i = 0; i < ratios.size(); i++) {
				if (maxRatio == null || maxRatio < ratios.get(i)) {
					maxRatio = ratios.get(i);
					betterChampion = champions.get(i);
					imax = i;
				}
			}
			betterRatios.add(maxRatio);
			betterChampions.add(betterChampion);
			champions.remove(imax);
			ratios.remove(imax);
		}
		LoLAutoCounterManager.getLogger().info("-----------------------");
		return betterChampions;
		
	}

	/**
	 * @param
	 * @param
	 * @return
	 */
	private float getScoreCounter(Champion champion, Champion championCountered, Lane laneCountered) {
		float counterScore = 0;
		for (Pick counter : laneCountered.getCounters()) {
			if (counter.getChampion().equals(champion)) {
				LoLAutoCounterManager.getLogger().info(counter.getChampion().getId()+" contre "+championCountered.getId()+" : "+counter.getRatio());
				counterScore += counter.getRatio();
				// in order to avoid duplicate data in
				// counter list
				break;
			}
		}
		return counterScore;
	}

	/**
	 * @param Champion
	 * @param Champion
	 * @return float
	 */
	private float getScoreCounter(Champion champion, Champion championCountered) {
		float counterScore = 0;
		for (Pick counter : championCountered.getCounters()) {
			if (counter.getChampion().equals(champion)) {
				LoLAutoCounterManager.getLogger().info(counter.getChampion().getId()+" contre "+championCountered.getId()+" : "+counter.getRatio());
				counterScore += counter.getRatio();
				// in order to avoid duplicate data in
				// counter list
				break;
			}
		}
		return counterScore;
	}

	/**
	 * @return the opponentsCharacters
	 */
	public List<PlayerSelection> getOpponentsCharacters() {
		return opponentsCharacters;
	}

	/**
	 * @return the teamCharacters
	 */
	public List<PlayerSelection> getTeamCharacters() {
		return teamCharacters;
	}

	/**
	 * @param opponentsCharacters
	 *            the opponentsCharacters to set
	 */
	public void setOpponentsCharacters(List<PlayerSelection> opponentsCharacters) {
		this.opponentsCharacters = opponentsCharacters;
	}

	/**
	 * @param teamCharacters
	 *            the teamCharacters to set
	 */
	public void setTeamCharacters(List<PlayerSelection> teamCharacters) {
		this.teamCharacters = teamCharacters;
	}

}
